package com.fingard.util;

import java.io.*;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import com.fingard.dsp.bank.directConfig.FtpSet;

/**
 * FTP工具类
 *
 */
public class FtpUtil {
	/**
	 * 连接FTP
	 *
	 * @param ftpHost
	 *            FTP主机服务器
	 * @param ftpPassword
	 *            FTP 登录密码
	 * @param ftpUserName
	 *            FTP登录用户名
	 * @param ftpPort
	 *            FTP端口 默认为21
	 * @return
	 */
	public static FTPClient getFTPClient(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort) {
		FTPClient ftpClient = new FTPClient();

		try {
			ftpClient = new FTPClient();

			// 连接FTP服务器
			ftpClient.connect(ftpHost, ftpPort);

			// 登陆FTP服务器
			ftpClient.login(ftpUserName, ftpPassword);

			// 关闭连接
			if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
				ftpClient.disconnect();
			}
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return ftpClient;
	}

	/**
	 * 从FTP服务器下载文件并保存到本地
	 *
	 * @param ftpHost
	 *            FTP IP地址
	 * @param ftpUserName
	 *            FTP 用户名
	 * @param ftpPassword
	 *            FTP用户名密码
	 * @param ftpPort
	 *            FTP端口
	 * @param ftpPath
	 *            FTP服务器中文件所在路径
	 * @param localPath
	 *            下载到本地的位置
	 * @param fileName
	 *            文件名称
	 * @throws Exception
	 */
	public static void downloadFtpFile(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort,
									   String ftpPath, String localPath, String fileName) throws Exception {

		FTPClient ftpClient = null;

		//try {
		ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);

		ftpClient.setControlEncoding("GBK");
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftpClient.enterLocalPassiveMode();
		ftpClient.changeWorkingDirectory(ftpPath.substring(1));

		File localFile = new File(localPath + File.separatorChar + fileName);
		OutputStream os = new FileOutputStream(localFile);

		fileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
		ftpClient.retrieveFile(fileName, os);
		os.flush();

		os.close();
		ftpClient.logout();
		//} catch (FileNotFoundException e1) {
		//	e1.printStackTrace();
		//} catch (SocketException e2) {
		//	e2.printStackTrace();
		//} catch (IOException e3) {
		//	e3.printStackTrace();
		//}

	}

	/**
	 * 读取本地文件内容
	 *
	 * @param filePath
	 *            本地文件路径
	 * @param encoding
	 *            字符编码
	 * @return
	 */
	public static String getTextFromFile(String filePath, String encoding) {
		String ftpStr = "";

		FileInputStream fis = null;
		InputStreamReader reader = null;
		BufferedReader br = null;

		try {
			File file = new File(filePath);

			if (!file.exists()) {
				throw new RuntimeException("对账单文件不存在");
			}

			fis = new FileInputStream(file);

			reader = new InputStreamReader(fis, encoding);
			br = new BufferedReader(reader);

			String line = "";
			while ((line = br.readLine()) != null) {
				if (line.equals("")) {
					continue;
				}

				ftpStr += line + "\r\n";
			}

			br.close();
			reader.close();
		} catch (Exception e1) {
			e1.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e2) {
					e2.printStackTrace();
				}
			}
		}

		return ftpStr;
	}

	/**
	 * 读取本地ZIP文件内容
	 *
	 * @param filePath
	 *            本地ZIP文件路径
	 * @return ZIP指定文件内容
	 * @throws IOException
	 */
	public static String getContentFromZip(String filePath) throws IOException {
		StringBuilder content = new StringBuilder();

		ZipFile zip = new ZipFile(filePath);

		@SuppressWarnings("unchecked")
		Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();

		ZipEntry ze = null;
		Scanner scanner = null;
		while (entries.hasMoreElements()) {
			ze = entries.nextElement();

			scanner = new Scanner(zip.getInputStream(ze));
			while (scanner.hasNextLine()) {
				content.append(scanner.nextLine() + "\r\n");
			}

			scanner.close();
		}

		zip.close();

		return content.toString();
	}

	/**
	 * 上传文件至sftp
	 * @param ftpSet
	 * @param localPath
	 * @param ftpFilePath
	 * @return
	 * @throws Exception
	 */
	public static int sftpUploading(FtpSet ftpSet, String localPath, String ftpFilePath) throws Exception{
		int result=-1;
		//建立连接
		SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
		//开始上传 sftp登录方式为用户名和密码
		FtpReceiver ftpReceiver = sftpPortClient.uploadFile("", localPath, ftpFilePath);
		sftpPortClient.disconnect();
		if (ftpReceiver.isCompleted) {
			result=0;//上传成功
		}
		return result;
	}

	/**
	 * 上传文件至ftp
	 * @param ftpSet
	 * @param localPath
	 * @param ftpFilePath
	 * @return
	 * @throws Exception
	 */
	public static int ftpUploading(FtpSet ftpSet, String localPath, String ftpFilePath) throws Exception{
		//建立连接
		FTPClient ftpClient=getFTPClient(ftpSet.serverIP,ftpSet.userName,ftpSet.userPassword,ftpSet.port);
		//开始上传
		int result = upload(ftpClient,localPath, ftpFilePath);
        ftpClient.disconnect();
		return result;
	}

	public static int upload(FTPClient ftpClient, String local, String remote) throws Exception {
		//设置PassiveMode传输
		ftpClient.enterLocalPassiveMode();
		//设置以二进制流的方式传输
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		ftpClient.setControlEncoding("GBK");
		//对远程目录的处理
		String remoteFileName = remote;
		if(remote.contains("/")) {
			remoteFileName = remote.substring(remote.lastIndexOf("/")+1);
			//创建服务器远程目录结构，创建失败直接返回
			if(createDirecroty(remote, ftpClient)==false) {
				return  -1;
			}
		}
		//检查远程是否存在文件
		FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"), "iso-8859-1"));
		if(files.length == 1) {
			//ftpClient.deleteFile(remote);
			return  1;
		}
		boolean result = uploadFile(remoteFileName, new File(local), ftpClient);
		if(result){
			return  0;
		}else {
			return  -1;
		}
	}

	private static boolean createDirecroty(String remote,FTPClient ftpClient) throws IOException{
		String directory = remote.substring(0,remote.lastIndexOf("/")+1);
		if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"),"iso-8859-1"))){
			//如果远程目录不存在，则递归创建远程服务器目录
			int start=0;
			int end = 0;
			if(directory.startsWith("/")){
				start = 1;
			}else{
				start = 0;
			}
			end = directory.indexOf("/",start);
			while(true){
				String subDirectory = new String(remote.substring(start,end).getBytes("GBK"),"iso-8859-1");
				if(!ftpClient.changeWorkingDirectory(subDirectory)){
					if(ftpClient.makeDirectory(subDirectory)){
						ftpClient.changeWorkingDirectory(subDirectory);
					}else {
						return false;
					}
				}
				start = end + 1;
				end = directory.indexOf("/",start);
				//检查所有目录是否创建完毕
				if(end <= start){
					break;
				}
			}
		}
		return true;
	}

	private static boolean uploadFile(String remoteFile, File localFile, FTPClient ftpClient) throws IOException {
		RandomAccessFile raf = new RandomAccessFile(localFile, "r");
		OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"),"iso-8859-1"));
		byte[] bytes = new byte[(int)raf.length()];
		int c;
		while((c = raf.read(bytes))!= -1){
			out.write(bytes,0,c);
		}
		out.flush();
		raf.close();
		out.close();
		return ftpClient.completePendingCommand();
	}

	/**
	 * 测试代码
	 *
	 * @param args
	 * @throws IOException
	 */
	/*public static void main(String[] args) throws IOException {
		String ftpHost = "127.0.0.1";
		String ftpUserName = "ftp01";
		String ftpPassword = "123456";
		int ftpPort = 22;
		String ftpPath = "/web";
		String localPath = "D:\\download";
		String fileName = "快钱MiniPos.txt";
		FtpUtil.downloadFtpFile(ftpHost, ftpUserName, ftpPassword, ftpPort, ftpPath, localPath, fileName);
	}*/
}
